-- 连接到服务端

local _M = {
    ip = "127.0.0.1",
    login_port = "8080",
    gate_port = "8888",
    gate_servername = "server1",

    username = "cauchy",
    password = "123",
} 

local socket = require "socket"
local crypt = require "client.crypt"

--[[
    resp: [
        uid, subid, gated, servername, secret
    ]
]]
function _M.connect_login_server()
    local function encode_token(token)
        return string.format("%s@%s",
            crypt.base64encode(token.user .. '\t' .. token.pass),
            crypt.base64encode(token.server))
    end

    local fd = socket.connect(_M.ip, _M.login_port)

    local token = {
        user = _M.username,
        pass = _M.password,
        server = _M.gate_servername,
    }

    local challenge = crypt.base64decode(socket.read_package(fd))
    local clientkey = crypt.randomkey()
    socket.send_package(fd, crypt.base64encode(crypt.dhexchange(clientkey)))

    local secret = crypt.dhsecret(crypt.base64decode(socket.read_package(fd)), clientkey)
    print("sceret : [ " .. crypt.hexencode(secret) .. " ] ")
    local hmac = crypt.hmac64(challenge, secret)
    socket.send_package(fd, crypt.base64encode(hmac))

    local token_encode = crypt.desencode(secret, encode_token(token))
    token_encode = crypt.base64encode(token_encode)
    socket.send_package(fd, token_encode)

    local result = socket.read_package(fd)
    local code = tonumber(string.sub(result, 1, 3))

    local resp = {} 

    if code ~= 200 then 
        resp.ok = false 
    else 
        local JS_user_online = crypt.base64decode(string.sub(result, 5))
        local user_online = require "cjson".decode(JS_user_online)
        -- login 服务返回的消息 user_online 

        resp.uid = user_online.uid -- 传输涉及编解码，uid太长，用string类型
        resp.subid = user_online.subid 
        resp.servername = user_online.servername 
        resp.gated = user_online.gated 
        resp.secret = user_online.secret
        resp.ok = true 
    end 
    
    socket.close(fd)

    return resp 
end 

-- return: fd
function _M.connect_gate_server(servername, uid, handshake_index, secret)
    local fd = assert(socket.connect(_M.ip, _M.gate_port))

    -- format uid@base64(servername)#index:base64(hmac) -- msgserver.lua: do_auth
    local handshake = string.format("%d@%s#%d", uid, crypt.base64encode(servername), handshake_index)
    local hmac = crypt.hmac64(crypt.hashkey(handshake), secret)

    local text = handshake .. ":" .. crypt.base64encode(hmac)

    socket.send_package(fd, text)

    local result = socket.read_package(fd)
    local code = tonumber(string.sub(result, 1, 3))

    if code == 200 then 
        return fd 
    end 
    return nil
end 

return _M 